# 交互式反馈 MCP 服务器
# 开发者：Fábio Ferreira (https://x.com/fabiomlferreira)
# 灵感来源：dotcursorrules.com (https://dotcursorrules.com/)
import os
import sys
import json
import tempfile
import subprocess

from typing import Annotated, Dict

from fastmcp import FastMCP
from pydantic import Field

# 设置日志级别为ERROR，这对Cline工具正常工作是必要的
# 参考：https://github.com/jlowin/fastmcp/issues/81
mcp = FastMCP("交互式反馈 MCP", log_level="ERROR")

def launch_feedback_ui(project_directory: str, summary: str) -> dict[str, str]:
    """
    启动反馈界面的核心函数
    
    Args:
        project_directory: 项目目录路径
        summary: 反馈摘要信息
        
    Returns:
        包含用户反馈结果的字典
    """
    # 确保项目目录路径存在且格式正确
    project_directory = os.path.abspath(os.path.normpath(project_directory))
    # 创建项目目录如果不存在
    os.makedirs(project_directory, exist_ok=True)
    
    # 创建临时文件存储反馈结果
    with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as tmp:
        output_file = tmp.name

    try:
        # 获取feedback_ui.py文件的相对路径
        script_dir = os.path.dirname(os.path.abspath(__file__))
        feedback_ui_path = os.path.join(script_dir, "feedback_ui.py")

        # 作为单独进程运行feedback_ui.py
        # 注意：由于uv存在的一个bug，我们需要传递特殊的标志来确保正常工作
        args = [
            sys.executable,     # Python解释器路径
            "-u",              # 无缓冲输出
            feedback_ui_path,  # 反馈界面脚本路径
            "--project-directory", project_directory,  # 项目目录参数
            "--prompt", summary,                       # 提示信息参数
            "--output-file", output_file               # 输出文件参数
        ]
        
        # 执行子进程，关闭所有标准输入输出以避免干扰
        result = subprocess.run(
            args,
            check=False,                    # 不自动检查返回码
            shell=False,                    # 不使用shell
            stdout=subprocess.DEVNULL,      # 重定向标准输出
            stderr=subprocess.DEVNULL,      # 重定向标准错误
            stdin=subprocess.DEVNULL,       # 重定向标准输入
            close_fds=True                  # 关闭文件描述符
        )
        
        # 检查进程返回码，如果非零则表示失败
        if result.returncode != 0:
            raise Exception(f"启动反馈界面失败，返回码: {result.returncode}")

        # 从临时文件读取反馈结果
        with open(output_file, 'r', encoding='utf-8') as f:
            result = json.load(f)
        # 清理临时文件
        os.unlink(output_file)
        return result
    except Exception as e:
        # 异常处理：确保临时文件被清理
        if os.path.exists(output_file):
            os.unlink(output_file)
        raise e

def first_line(text: str) -> str:
    """
    提取文本的第一行并去除首尾空格
    
    Args:
        text: 输入文本
        
    Returns:
        第一行文本，去除首尾空格
    """
    return text.split("\n")[0].strip()

@mcp.tool()
def interactive_feedback(
    project_directory: Annotated[str, Field(description="项目目录的完整路径")],
    summary: Annotated[str, Field(description="更改的简短一行总结")],
) -> Dict[str, str]:
    """
    MCP工具函数：为给定的项目目录和总结请求交互式反馈
    
    这是MCP服务器对外提供的主要接口，AI助手会调用此函数来获取用户反馈
    
    Args:
        project_directory: 项目目录的完整路径
        summary: 更改的简短一行总结
        
    Returns:
        包含用户反馈信息的字典
    """
    # 确保项目目录是有效路径
    project_dir = first_line(project_directory)
    # 如果路径不存在或不是绝对路径，尝试转换为绝对路径
    if not os.path.isabs(project_dir):
        project_dir = os.path.abspath(project_dir)
    
    # 确保目录存在，不存在则创建
    os.makedirs(project_dir, exist_ok=True)
        
    return launch_feedback_ui(project_dir, first_line(summary))

# 主程序入口：启动MCP服务器
if __name__ == "__main__":
    # 使用stdio传输协议运行MCP服务器
    mcp.run(transport="stdio")
